package io.hankers.falconv.util;

import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.Toast;

import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;

import io.hankers.falconv.MyApplication;

import static android.content.Context.MODE_PRIVATE;

public class AutoUpgrade {
    private static final String TAG = "AutoUpgrade";
    // Example
    // {"code":4,"name":"1.0.4","url":"https://YOUR/URL/APP.apk","comments":""}
    private static final String VERSION_URL = "https://app2u.cn:9090/js/falconv/version.json";

    public static void checkUpgrade() {
        if (!checkWifiOnAndConnected()) {
            Log.i(TAG, "NO WIFI");
            return;
        }

        if (!checkInterval()) {
            Log.i(TAG, "Failed to check Interval");
            return;
        }

        new ReadJSONTask().execute();
    }

    private static void upgrade(String packageName, int newVersionCode, String apkUrl) {
        Context context = MyApplication.getAppContext();

//        String destination = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/";
        String destination = context.getExternalCacheDir() + "/";
        String fileName = packageName + "-" + newVersionCode + ".apk";
        destination += fileName;
        final Uri uri = Uri.parse("file://" + destination);

        //Delete update file if exists
        File file = new File(destination);
        if (file.exists())
            //file.delete() - test this, I think sometimes it doesnt work
            file.delete();

        final DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);

        DownloadManager.Query query = new DownloadManager.Query();
        query.setFilterByStatus(DownloadManager.STATUS_RUNNING);

        Cursor cursor = downloadManager.query(query);
        if (cursor.moveToFirst()) {
            do {
                String url = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_URI));
                Log.d(TAG, url);
                if (url.compareToIgnoreCase(apkUrl) == 0) {
                    // duplicated
                    Log.d(TAG, "Duplicated downloading " + url);
                    return;
                }
            } while (cursor.moveToNext());
        }

        //set downloadmanager
        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(apkUrl));
        request.setTitle("下载升级包...");
        Toast.makeText(context, "下载升级包...", Toast.LENGTH_SHORT).show();

        //set destination
        request.setDestinationUri(uri);

        // get download service and enqueue file
        final long downloadId = downloadManager.enqueue(request);

        //set BroadcastReceiver to install app when .apk is downloaded
        BroadcastReceiver onComplete = new BroadcastReceiver() {
            public void onReceive(Context ctxt, Intent intent) {
                // 1. android.permission.REQUEST_INSTALL_PACKAGES
                // 2. Strict Mode in Application.onCreate for FileUriExposedException, https://stackoverflow.com/a/40674771
                Intent install = new Intent(Intent.ACTION_VIEW);
                install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                install.setDataAndType(uri,
                        downloadManager.getMimeTypeForDownloadedFile(downloadId));
                context.startActivity(install);

                context.unregisterReceiver(this);
//                finish();
            }
        };
        //register receiver for when .apk download is compete
        context.registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
    }

    private static JSONObject readJson() {
        try {
            URL url = new URL(VERSION_URL);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(60000);

            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            StringBuilder sb = new StringBuilder();
            String str;
            while ((str = in.readLine()) != null) {
                sb.append(str);
            }
            in.close();

            String versionStr = sb.toString();
            Log.i(TAG, "Remote version = " + versionStr);
            JSONObject json = new JSONObject(versionStr);
            return json;
        } catch (Exception e) {
            Log.e(TAG, e.toString());
        }
        return null;
    }

    private static boolean checkWifiOnAndConnected() {
        Context context = MyApplication.getAppContext();

        WifiManager wifiMgr = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);

        if (wifiMgr.isWifiEnabled()) { // Wi-Fi adapter is ON

            WifiInfo wifiInfo = wifiMgr.getConnectionInfo();

            if( wifiInfo.getNetworkId() == -1 ){
                return false; // Not connected to an access point
            }
            return true; // Connected to an access point
        }
        else {
            return false; // Wi-Fi adapter is OFF
        }
    }

    private static boolean checkInterval() {
        Context context = MyApplication.getAppContext();

        final String key = "last_time_of_check_upgrading";

        SharedPreferences sp = context.getSharedPreferences(TAG, MODE_PRIVATE);
        long last_time_of_check_upgrading = sp.getLong(key, 0);

        long now = new Date().getTime();
        if (now - last_time_of_check_upgrading < 24 * 3600 * 1000) {
            return false;
        }

        SharedPreferences.Editor speditor = sp.edit();
        speditor.putLong(key, now);
        speditor.apply();

        return true;
    }

    static class ReadJSONTask extends AsyncTask<String, Void, JSONObject> {

        private Exception exception;

        protected JSONObject doInBackground(String... urls) {
            return readJson();
        }

        protected void onPostExecute(JSONObject remoteVersion) {
            try {
                Context ctx = MyApplication.getAppContext();

                PackageInfo pInfo = ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), 0);
                long versionCode = pInfo.getLongVersionCode();

                if (remoteVersion != null && remoteVersion.getInt("code") > versionCode) {
                    upgrade(pInfo.packageName,
                            remoteVersion.getInt("code"),
                            remoteVersion.getString("url"));
                } else {
                    Log.i(TAG, "no later version for " + pInfo.versionName);
                }
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}
